package sistema;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.util.Calendar;
import java.util.Scanner;

public class GerenciadorMaquinasFixas implements Gerenciador {
	private static File diretorioBroker = new File("/home/isabellylr/broker");
	private static File diretorioArquivos = new File("/home/isabellylr/workspace/Sistema/");
	private static int INDICE_GERADOR, INDICE_FILTRO, INDICE_CONTADOR, indiceUmGerador,
						indiceOutroGerador, indiceUmFiltro, indiceOutroFiltro, indiceUmContador, 
						indiceOutroContador, tempoInicial, quantidadeDeMinutos;
	private static Scanner sc = new Scanner(System.in);
	
	@Override
	public void gerenciar() {
		try {
			tempoInicial = Calendar.getInstance().get(Calendar.MINUTE); 
			System.out.print("Por quantos minutos deseja executar o programa? ");
			quantidadeDeMinutos = sc.nextInt();
			iniciarBroker();
			realizarTarefas();
			finalizarBroker();
		} catch (Exception ex) { 
			System.err.println("Erro! " + ex.getMessage());
		}
	}

	private boolean iniciarBroker() throws Exception {
		Process p = Runtime.getRuntime().exec("bash broker start", null, diretorioBroker);
		BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
		String linha = "";
		while ((linha = reader.readLine()) != null) {
			System.out.println(linha);
			if (linha.contains("successfully started")) {
				return true;
			}
		}
		return iniciarBroker();
	}
	
	private void realizarTarefas() throws Exception {
		while (Calendar.getInstance().get(Calendar.MINUTE) < (tempoInicial + quantidadeDeMinutos)) {
			if (terminouJob("UmGeradorDeNumeros" + indiceUmGerador)) {
				imprimirStatus("arquivo" + indiceUmGerador);
				criaGeradorDeNumerosJDF("UmGeradorDeNumeros");
				executarJob("UmGeradorDeNumeros" + INDICE_GERADOR);
				indiceUmGerador = INDICE_GERADOR;
			} if (terminouJob("OutroGeradorDeNumeros" + indiceOutroGerador)) {
				imprimirStatus("arquivo" + indiceOutroGerador);
				criaGeradorDeNumerosJDF("OutroGeradorDeNumeros");
				executarJob("OutroGeradorDeNumeros" + INDICE_GERADOR);
				indiceOutroGerador = INDICE_GERADOR;
			} if (terminouJob("UmFiltro" + indiceUmFiltro) && encontraArquivo("arquivo" + (INDICE_FILTRO + 1))) {
				imprimirStatus("arquivoFiltrado" + indiceUmFiltro);
				criaFiltroJDF("UmFiltro");
				executarJob("UmFiltro" + INDICE_FILTRO);
				indiceUmFiltro = INDICE_FILTRO;
			} if (terminouJob("OutroFiltro" + indiceOutroFiltro) && encontraArquivo("arquivo" + (INDICE_FILTRO + 1))) {
				imprimirStatus("arquivoFiltrado" + indiceOutroFiltro);
				criaFiltroJDF("OutroFiltro");
				executarJob("OutroFiltro" + INDICE_FILTRO);
				indiceOutroFiltro = INDICE_FILTRO;
			} if (terminouJob("UmContadorDeOcorrencia" + indiceUmContador) && encontraArquivo("arquivoFiltrado" + (INDICE_CONTADOR + 1))) {
				imprimirStatus("Ocorrencia1");
				criaContadorDeOcorrenciaJDF("UmContadorDeOcorrencia", "Ocorrencia1");
				executarJob("UmContadorDeOcorrencia" + INDICE_CONTADOR);
				indiceUmContador = INDICE_CONTADOR;
			} if (terminouJob("OutroContadorDeOcorrencia" + indiceOutroContador) && encontraArquivo("arquivoFiltrado" + (INDICE_CONTADOR + 1))) {
				imprimirStatus("Ocorrencia2");
				criaContadorDeOcorrenciaJDF("OutroContadorDeOcorrencia", "Ocorrencia2");
				executarJob("OutroContadorDeOcorrencia" + INDICE_CONTADOR);
				indiceOutroContador = INDICE_CONTADOR;
			}
		}
	}
	
	private void finalizarBroker() throws Exception {
		if (!terminouTodosOsJobs()) {
			Thread.sleep(600);
			finalizarBroker();
		}
		Runtime.getRuntime().exec("bash broker stop", null, diretorioBroker);
	}
	
	private boolean terminouTodosOsJobs() throws Exception {
		Process p = Runtime.getRuntime().exec("bash broker status", null, diretorioBroker);
		BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
		String linha = "";
		while ((linha = reader.readLine()) != null) {
			if (linha.contains("[RUNNING]") || linha.contains("[UNSTARTED]")) {
				return false;
			}
		}
		return true;
	}
	
	private void criaGeradorDeNumerosJDF(String job) throws Exception {
		FileOutputStream geradorDeNumeros = new FileOutputStream("Jobs/" + job + ++INDICE_GERADOR + ".jdf");
		geradorDeNumeros.write(("job :\nlabel 	: " + job + INDICE_GERADOR + "\n\ntask :\n" +
		"init 	: put " + diretorioArquivos + "/bin/sistema/GeradorDeNumeros.class GeradorDeNumeros.class\n" +
		"remote 	: java -cp . GeradorDeNumeros arquivo" + INDICE_GERADOR + "\n" +
		"final   : get arquivo" + INDICE_GERADOR + " " + diretorioArquivos + "/Files/arquivo" + INDICE_GERADOR).getBytes());
	}
	
	private void criaFiltroJDF(String job) throws Exception {
		FileOutputStream filtroJDF = new FileOutputStream("Jobs/" + job + ++INDICE_FILTRO + ".jdf");
		filtroJDF.write(("job :\nlabel 	: " + job + INDICE_FILTRO + "\n\ntask :\n" +
		"init 	: put " + diretorioArquivos + "/Files/arquivo" + INDICE_FILTRO + " arquivo" + INDICE_FILTRO + "\n" +
		"put " + diretorioArquivos + "/bin/sistema/Filtro.class Filtro.class\n" +
		"remote 	: java -cp . Filtro arquivo" + INDICE_FILTRO + " arquivoFiltrado" + INDICE_FILTRO + "\n" +
		"final   : get arquivoFiltrado" + INDICE_FILTRO + " " + diretorioArquivos + "/Files/arquivoFiltrado" + INDICE_FILTRO).getBytes());
	}
	
	private void criaContadorDeOcorrenciaJDF(String job, String arquivo) throws Exception {
		FileOutputStream contadorDeOcorrenciaJDF = new FileOutputStream("Jobs/" + job + ++INDICE_CONTADOR + ".jdf");
		contadorDeOcorrenciaJDF.write(("job :\nlabel 	: " + job + INDICE_CONTADOR + "\n\ntask :\ninit 	: " +
		"put " + diretorioArquivos + "/Files/arquivoFiltrado" + INDICE_CONTADOR + " arquivoFiltrado" + INDICE_CONTADOR + "\n" +
		"put " + diretorioArquivos + "/" + arquivo + " " + arquivo +"\n" +
		"put " + diretorioArquivos + "/bin/sistema/ContadorDeOcorrencia.class ContadorDeOcorrencia.class\n" +
		"remote 	: java -cp . ContadorDeOcorrencia arquivoFiltrado" + INDICE_CONTADOR + " " + arquivo + "\n" +
		"final   : get " + arquivo + " " + diretorioArquivos + "/" + arquivo).getBytes());
	}
	
	private void executarJob(String job) throws Exception {
		imprime(Runtime.getRuntime().exec("bash broker addjob " + diretorioArquivos + "/Jobs/" + job + ".jdf", null, diretorioBroker));
	}
	
	private boolean encontraArquivo(String arquivo) throws Exception {
		return (new File(diretorioArquivos + "/Files/" + arquivo)).exists();
	}
	
	private boolean terminouJob(String job) throws Exception {
		Process p = Runtime.getRuntime().exec("bash broker status", null, diretorioBroker);
		BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
		String linha = "";
		while ((linha = reader.readLine()) != null) {
			if (linha.contains(job)) {
				return linha.contains("[FINISHED]");
			}
		}
		return true;
	}
	
	private void imprimirStatus(String arquivoNome) throws Exception {
		BufferedReader arquivo = new BufferedReader(new FileReader(arquivoNome));
		String linha = "";
		while ((linha = arquivo.readLine()) != null) {
			if (linha.contains("Informacoes")) {
				System.out.println("-\n" + linha + "\n-");
			}
		}
	}

	private void imprime(Process p) throws Exception {
		BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
		String linha = "";
		while ((linha = reader.readLine()) != null) {
			System.out.println(linha);
		}
	}
}